package cgs

import (
	"cgs-server/helper"
	"cgs-server/server"
	"fmt"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"io"
	"net/http"
	"os"
	"strings"
	"time"
)

func init() {
	//server.Handle(http.MethodPost, "/api/Cgs/File/Create", CreateFile, server.SaveScene)
	//server.Handle(http.MethodPost, "/api/Cgs/File/Save", SaveFile, server.SaveScene)
	//server.Handle(http.MethodPost, "/api/Cgs/File/Delete", DeleteFile, server.DeleteScene)
	//server.Handle(http.MethodPost, "/api/Cgs/File/ChangeName", ReNameFile, server.SaveScene)
	//server.Handle(http.MethodPost, "/api/Cgs/File/UploadImage", UploadImage, server.SaveScene)

	server.Post("/api/Cgs/File/Create", CreateFile, "创建文件", server.Login)
	server.Post("/api/Cgs/File/Save", SaveFile, "保存文件", server.Login)
	server.Post("/api/Cgs/File/Delete", DeleteFile, "删除文件", server.Login)
	server.Post("/api/Cgs/File/ChangeName", ReNameFile, "更新文件名称", server.Login)
	server.Post("/api/Cgs/File/UploadImage", UploadImage, "上传图片", server.Login)
}
func UploadImage(w http.ResponseWriter, r *http.Request) {
	collectionName := "_CgsProject"
	r.ParseMultipartForm(server.Config.Upload.MaxSize)
	r.ParseForm()
	files := r.MultipartForm.File
	if len(files) != 1 {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  "Please select an file.",
		})
		return
	}
	file := files["file"][0]
	fileName := file.Filename
	//fileSize := file.Size
	//fileType := file.Header.Get("Content-Type")
	//fileExt := filepath.Ext(fileName)
	//fileNameWithoutExt := strings.TrimSuffix(fileName, fileExt)
	pid, err := primitive.ObjectIDFromHex(strings.TrimSpace(r.FormValue("projId")))
	savePath := fmt.Sprintf("/Upload/Cgs/%v", pid.Hex())
	filePath := fmt.Sprintf("%v/%v", savePath, fileName)
	physicalPath := server.MapPath(savePath)
	target, err := os.Create(fmt.Sprintf("%v/%v", physicalPath, fileName))
	defer target.Close()
	source, err := file.Open()
	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  err.Error(),
		})
		return
	}
	defer source.Close()
	io.Copy(target, source)

	doc := bson.M{}
	//find, _ := db.FindOne(collectionName, filter, &doc)
	id := primitive.NewObjectID()
	now := time.Now()
	doc = bson.M{
		"ID":       id,
		"ParentId": pid,
		"Name":     fileName,
		//"Data":       data,
		"FilePath":   filePath,
		"FileType":   "IMG",
		"CreateTime": now,
		"UpdateTime": now,
		"type":       r.FormValue("type"),
	}
	if server.Config.Authority.Enabled {
		user, _ := server.GetCurrentUser(r)
		if user != nil {
			doc["UserID"] = user.ID
			doc["tenantId"] = user.TenantId
		}
	}
	db, err := server.Mongo()
	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  err.Error(),
		})
		return
	}
	db.InsertOne(collectionName, doc)
	helper.WriteJSON(w, server.Result{
		Code: 200,
		Msg:  "Saved successfully!",
	})

}

func CreateFile(w http.ResponseWriter, r *http.Request) {

	collectionName := "_CgsProject"
	r.ParseForm()
	pid, err := primitive.ObjectIDFromHex(strings.TrimSpace(r.FormValue("PID")))

	name := strings.TrimSpace(r.FormValue("Name"))
	if name == "" {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  "Name is not allowed to be empty.",
		})
		return
	}
	if strings.HasPrefix(name, "_") {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  "Name is not allowed to start with _.",
		})
		return
	}
	//save file to /Upload/Cgs/$ID/timestap.js
	fileName := name
	savePath := fmt.Sprintf("/Upload/Cgs/%v", pid.Hex())
	filePath := fmt.Sprintf("%v/%v", savePath, fileName)
	physicalPath := server.MapPath(savePath)

	if _, err := os.Stat(physicalPath); os.IsNotExist(err) {
		os.MkdirAll(physicalPath, 0755)
	}
	target, err := os.Create(fmt.Sprintf("%v/%v", physicalPath, fileName))
	defer target.Close()
	if err != nil {

	} else {
		//_, err = target.WriteString(data)
	}

	db, err := server.Mongo()
	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  err.Error(),
		})
		return
	}
	//filter := bson.M{
	//	"ID": pid,
	//}
	doc := bson.M{}
	//find, _ := db.FindOne(collectionName, filter, &doc)
	id := primitive.NewObjectID()
	now := time.Now()
	doc = bson.M{
		"ID":       id,
		"ParentId": pid,
		"Name":     fileName,

		"FileType": "JS",
		//"Data":       data,
		"FilePath":   filePath,
		"CreateTime": now,
		"UpdateTime": now,
		"type":       r.FormValue("type"),
	}
	if server.Config.Authority.Enabled {
		user, _ := server.GetCurrentUser(r)
		if user != nil {
			doc["UserID"] = user.ID
			doc["tenantId"] = user.TenantId
		}
	}
	db.InsertOne(collectionName, doc)
	helper.WriteJSON(w, server.Result{
		Code: 200,
		Msg:  "Saved successfully!",
	})
}

func SaveFile(w http.ResponseWriter, r *http.Request) {
	collectionName := "_CgsProject"
	r.ParseForm()
	id, err := primitive.ObjectIDFromHex(strings.TrimSpace(r.FormValue("ID")))
	if err != nil {
		//report error
	}
	data := strings.TrimSpace(r.FormValue("Data"))
	filePath := strings.TrimSpace(r.FormValue("FilePath"))
	//now := time.Now()
	//save file to /Upload/Cgs/$ID/timestap.js
	filter := bson.M{
		"ID": id,
	}
	doc := CgsProj{}
	db, err := server.Mongo()
	find, _ := db.FindOne(collectionName, filter, &doc)
	if !find {
		//report error
	}
	if doc.FileType == "IMG" {
		helper.WriteJSON(w, server.Result{
			Code: 200,
			Msg:  "图片不允许重新保存，请选择js文件进行保存",
		})
		return
	}
	// wirte to file
	//fileName := fmt.Sprintf("%v.js", helper.TimeToString(now, "yyyyMMddHHmmss"))
	//savePath := fmt.Sprintf("/Upload/Cgs/%v", id.Hex())
	//filePath := fmt.Sprintf("%v/%v", savePath, fileName)
	physicalPath := server.MapPath(filePath)
	if _, err := os.Stat(physicalPath); os.IsNotExist(err) {
		os.MkdirAll(physicalPath, 0755)
	}
	target, err := os.OpenFile(physicalPath, os.O_WRONLY|os.O_TRUNC, 0755)
	defer target.Close()
	if err != nil {

	} else {
		_, err = target.WriteString(data)
	}

	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  err.Error(),
		})
		return
	}

	helper.WriteJSON(w, server.Result{
		Code: 200,
		Msg:  "Saved successfully!",
	})

}

func DeleteFile(w http.ResponseWriter, r *http.Request) {
	collectionName := "_CgsProject"
	r.ParseForm()
	id, err := primitive.ObjectIDFromHex(r.FormValue("ID"))
	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  "ID is not allowed.",
		})
		return
	}

	db, err := server.Mongo()
	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  err.Error(),
		})
		return
	}

	filter := bson.M{
		"ID": id,
	}

	doc := bson.M{}
	find, _ := db.FindOne(collectionName, filter, &doc)

	if !find {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  "The project is not existed.",
		})
		return
	}

	// delete scene summary
	db.DeleteOne(collectionName, filter)

	helper.WriteJSON(w, server.Result{
		Code: 200,
		Msg:  "Delete successfully!",
	})
}

func ReNameFile(w http.ResponseWriter, r *http.Request) {
	collectionName := "_CgsProject"
	r.ParseForm()
	id, err := primitive.ObjectIDFromHex(strings.TrimSpace(r.FormValue("ID")))
	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  err.Error(),
		})
		return
	}
	name := strings.TrimSpace(r.FormValue("Name"))

	if name == "" {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  "Name is not allowed to be empty.",
		})
		return
	}
	if strings.HasPrefix(name, "_") {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  "Name is not allowed to start with _.",
		})
		return
	}
	now := time.Now()

	db, err := server.Mongo()
	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  err.Error(),
		})
		return
	}
	filter := bson.M{
		"ID": id,
	}
	doc := bson.M{}
	find, _ := db.FindOne(collectionName, filter, &doc)

	if !find {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  "Can not find project with ID " + id.String(),
		})
	} else {
		if server.Config.Authority.Enabled {
			user, _ := server.GetCurrentUser(r)
			// save other people's scene
			if doc["UserID"] != nil && doc["UserID"].(string) != user.ID {
				helper.WriteJSON(w, server.Result{
					Code: 300,
					Msg:  "Permission denied.",
				})
				return
			}
			// not admin save scene without UserID
			if doc["UserID"] == nil && user.RoleName != "Administrator" {
				helper.WriteJSON(w, server.Result{
					Code: 300,
					Msg:  "Permission denied.",
				})
				return
			}
		}
		filePath := doc["FilePath"].(string)

		oldName := doc["Name"]
		if oldName == name {
			helper.WriteJSON(w, server.Result{
				Code: 300,
				Msg:  "Name Not Changed",
			})
			return
		}
		parentId := doc["ParentId"].(primitive.ObjectID).Hex()
		oldPhysicalPath := server.MapPath(filePath)
		fileName := name
		savePath := fmt.Sprintf("/Upload/Cgs/%v/%v", parentId, fileName)
		newPhysicalPath := server.MapPath(savePath)
		os.Rename(oldPhysicalPath, newPhysicalPath)

		update := bson.M{
			"$set": bson.M{
				"Name":       fileName,
				"UpdateTime": now,
				"FilePath":   savePath,
			},
		}
		db.UpdateOne(collectionName, filter, update)

	}

	helper.WriteJSON(w, server.Result{
		Code: 200,
		Msg:  "Saved successfully!",
	})

}
